#ifndef _BUFFER_
#define _BUFFER_

#include <vector>
#include <stddef.h>
#include <string>
#include <algorithm>

//
class Buffer{
public:

    static const size_t kCheapPrepend = 8;
    static const size_t kInitialSize = 1024;

    explicit Buffer(size_t initialSize = kInitialSize)
        : buffer_(kCheapPrepend + initialSize)
        , readerIndex_(kCheapPrepend)
        , writeIndex_(kCheapPrepend)
        {}  

    size_t readableBytes() const
    {
        return writeIndex_ - readerIndex_;
    }
    size_t writableBytes() const
    {
        return buffer_.size() - writeIndex_;
    }
    size_t prependableBytes() const
    {
        return readerIndex_;
    }
    const char* peek() const
    {
        return begin() + readerIndex_;
    }
    //onMessage string <- Buffer
    void retrieve(size_t len)
    {
        if(len < readableBytes())
        {
            readerIndex_ += len;
        }
        else
        {
            //read over, write reuse
            readerIndex_ = writeIndex_ = kCheapPrepend;
        }
    }

    void retrieveAll()
    {

    }
    //Buffer -> string
    std::string retrieveAllString()
    {
        return retrieveAsString(readableBytes());
    }
    std::string retrieveAsString(size_t len)
    {
        std::string result(peek(), len);
        retrieve(len);
        return result;
    }
    void ensureWritableBytes(size_t len)
    {
        if(writableBytes() < len)
        {
            makeSpace(len);
        }
        else
        {
            writeIndex_ += len;
        }
    }
    char* beginWrite()
    {
        return begin() + writeIndex_;
    }
    const char* beginWrite() const
    {
        return begin() + writeIndex_;
    }
    void append(const char *data, size_t len)
    {
        ensureWritableBytes(len);
        std::copy(data, data + len, beginWrite());
        writeIndex_ += len;
    }
    //从fd上读取数据
    size_t readFd(int fd, int* saveErrno);
private:
    void makeSpace(size_t len)
    {
        //The available free space in the buffer is insufficient to accommodate the required length for writing.
        if(writableBytes() + prependableBytes() < kCheapPrepend + len)
        {
            buffer_.resize(writeIndex_ + len);
        }
        else
        {
            std::copy(begin() + readerIndex_, begin() + writeIndex_, begin() + kCheapPrepend);
            readerIndex_ = kCheapPrepend;
            writeIndex_ = readerIndex_ + readableBytes();
        }
    }
    //the first element of vector , is also the first address of array
    char* begin()
    {
        return &*buffer_.begin();
    }
    const char* begin() const
    {
        return &*buffer_.begin();
    }
    //why vector, expand capacity is easy
    std::vector<char> buffer_;
    size_t readerIndex_;
    size_t writeIndex_;
};

#endif